
module	VgaController(	//	Host Side
						r_address1,
						r_stop1,
						r_data1,
						r_data_avai1,
						//	VGA Side
						oVGA_R,
						oVGA_G,
						oVGA_B,
						oVGA_H_SYNC,
						oVGA_V_SYNC,
						oVGA_SYNC,
						oVGA_BLANK,

						//	Control Signal
						iVGA_CLK,
						iSRAM_CLK,
						iRST_N,
						iSW,
						oRequest
							);

`include "VGA_Param.h"

//	Host Side
input	wire	[31:0]	r_data1;
input	wire			r_data_avai1;
output	wire			r_stop1;
output 	reg		[18:0]	r_address1;
			
//	VGA Side
output	reg	[9:0]	oVGA_R;
output	reg	[9:0]	oVGA_G;
output	reg	[9:0]	oVGA_B;
output	reg			oVGA_H_SYNC;
output	reg			oVGA_V_SYNC;
output	reg			oVGA_SYNC;
output	reg			oVGA_BLANK;

wire		[9:0]	mVGA_R;
wire		[9:0]	mVGA_G;
wire		[9:0]	mVGA_B;
reg					mVGA_H_SYNC;
reg					mVGA_V_SYNC;
wire				mVGA_SYNC;
wire				mVGA_BLANK;
reg					oRequest;
wire		[31:0]	GRAY;
reg			[7:0]	VGA,Red,Green,Blue;
//	Control Signal
input	wire	[17:0]	iSW;
input				iVGA_CLK;
input				iSRAM_CLK;
input				iRST_N;
output				oRequest;

//	Internal Registers and Wires
reg		[12:0]		H_Cont;
reg		[12:0]		V_Cont;

wire	[12:0]		v_mask;



reg	 [1:0]	byte_no0;
reg	 [1:0]	pre_byte_no0;

always @(posedge iVGA_CLK or negedge iRST_N)begin
	if (!iRST_N)begin
		byte_no0 	<= 2'b00;
//		pre_byte_no0<=2'b11;
	end
	else begin
		if (oRequest) begin
			byte_no0	<=	byte_no0 + 2'b01;
			case (byte_no0)
				2'b00: VGA	<=	GRAY[23:16];
				2'b01: VGA	<=	GRAY[31:24];
				2'b10: VGA	<=	GRAY[7:0];
				2'b11: VGA	<=	GRAY[15:8];
			endcase
		end
	end
end

reg rinc0;
always @ (posedge iVGA_CLK) begin
	pre_byte_no0 <= byte_no0;
	if ((byte_no0 == 2'b00)&&(pre_byte_no0 == 2'b11))
		rinc0 <= 1;
	else
		rinc0 <= 0;
	end

//always @ (posedge iVGA_CLK) begin
//	
//	if (oRequest&&(byte_no0==2'b00)) 
//		rinc0 <= 1;
//	else
//		rinc0 <= 0;
//	end
reg	 [19:0]	VGA_OP;
always @(posedge iVGA_CLK or negedge iRST_N)begin
	if (!iRST_N)begin
		VGA_OP 	<= 0;
	end
	else begin
			case (iSW[14:13])
				2'b00: VGA_OP	<=	19'h00000;
				2'b01: VGA_OP	<=	19'h12C00;
				2'b10: VGA_OP	<=	19'h25800;
				2'b11: VGA_OP	<=	19'h38400;
			endcase
	end
end

always @ (posedge iSRAM_CLK or negedge oRequest) begin
  if (!oRequest) begin
    r_address1 	<= {(V_Cont-Y_START),7'b0000000}+{(V_Cont-Y_START),5'b00000}+VGA_OP;	// 640 pixels
  end
  else begin
	if (r_data_avai1_s && !r_stop1)
		r_address1 <= r_address1 +1;
  end
end
always @ (posedge iSRAM_CLK )
    r_data_avai1_s 	<= r_data_avai1;	// 640 pixels

wire wfull1;
reg r_data_avai1_s;
assign r_stop1	= (!oRequest) | wfull1;		 
fifo1	VGA_FIFO (
					.rdata(GRAY),
					.wfull(wfull1),
					.rempty(),
					.wdata(r_data1),
					.winc(r_data_avai1_s), .wclk(iSRAM_CLK), .wrst_n(oRequest),//oRequest
					.rinc(rinc0), .rclk(iVGA_CLK), .rrst_n(oRequest)//oRequest
				 );	
				 
				 
wire	sRequest_1;
wire	sRequest_2;

shift_1x32 U3(
		   .clk(iVGA_CLK), 
			.shift(1'b1),
			.sr_in(oRequest),
			.sr_out_1(sRequest_1),
			.sr_out_2(sRequest_2)
		   );
//		   
//wire	r_data_avai1_1;
//wire	r_data_avai1_2;		   
//shift_1x32 U4(
//		   .clk(iSRAM_CLK), 
//			.shift(1'b1),
//			.sr_in(r_data_avai1),
//			.sr_out_1(r_data_avai1_1),
//			.sr_out_2(r_data_avai1_2)
//		   );

assign	mVGA_BLANK	=	mVGA_H_SYNC & mVGA_V_SYNC;
assign	mVGA_SYNC	=	1'b0;

assign	mVGA_R	=	(	H_Cont>=X_START 	&& H_Cont<X_START+H_SYNC_ACT &&
						V_Cont>=Y_START 	&& V_Cont<Y_START+V_SYNC_ACT )
						?	VGA	:	0;
assign	mVGA_G	=	(	H_Cont>=X_START 	&& H_Cont<X_START+H_SYNC_ACT &&
						V_Cont>=Y_START 	&& V_Cont<Y_START+V_SYNC_ACT )
						?	VGA	:	0;
assign	mVGA_B	=	(	H_Cont>=X_START 	&& H_Cont<X_START+H_SYNC_ACT &&
						V_Cont>=Y_START 	&& V_Cont<Y_START+V_SYNC_ACT )
						?	VGA	:	0;

always@(posedge iVGA_CLK or negedge iRST_N)
	begin
		if (!iRST_N)
			begin
				oVGA_R <= 0;
				oVGA_G <= 0;
                oVGA_B <= 0;
				oVGA_BLANK <= 0;
				oVGA_SYNC <= 0;
				oVGA_H_SYNC <= 0;
				oVGA_V_SYNC <= 0; 
			end
		else
			begin
				oVGA_R[9:2] <= mVGA_R;
				oVGA_G[9:2] <= mVGA_G;
                oVGA_B[9:2] <= mVGA_B;
				oVGA_BLANK <= mVGA_BLANK;
				oVGA_SYNC <= mVGA_SYNC;
				oVGA_H_SYNC <= mVGA_H_SYNC;
				oVGA_V_SYNC <= mVGA_V_SYNC;				
			end               
	end



//	Pixel LUT Address Generator
always@(posedge iVGA_CLK or negedge iRST_N)
begin
	if(!iRST_N)
	oRequest	<=	0;
	else
	begin
		if(	H_Cont>=X_START-4 && H_Cont<X_START+H_SYNC_ACT-4 &&
			V_Cont>=Y_START && V_Cont<Y_START+V_SYNC_ACT )
		oRequest	<=	1;
		else
		oRequest	<=	0;
	end
end



//	H_Sync Generator, Ref. 25.175 MHz Clock
always@(posedge iVGA_CLK or negedge iRST_N)
begin
	if(!iRST_N)
	begin
		H_Cont		<=	0;
		mVGA_H_SYNC	<=	0;
	end
	else
	begin
		//	H_Sync Counter
		if( H_Cont < H_SYNC_TOTAL )
		H_Cont	<=	H_Cont+1;
		else
		H_Cont	<=	0;
		//	H_Sync Generator
		if( H_Cont < H_SYNC_CYC )
		mVGA_H_SYNC	<=	0;
		else
		mVGA_H_SYNC	<=	1;
	end
end

//	V_Sync Generator, Ref. H_Sync
always@(posedge iVGA_CLK or negedge iRST_N)
begin
	if(!iRST_N)
	begin
		V_Cont		<=	0;
		mVGA_V_SYNC	<=	0;
	end
	else
	begin
		//	When H_Sync Re-start
		if(H_Cont==0)
		begin
			//	V_Sync Counter
			if( V_Cont < V_SYNC_TOTAL )
			V_Cont	<=	V_Cont+1;
			else
			V_Cont	<=	0;
			//	V_Sync Generator
			if(	V_Cont < V_SYNC_CYC )
			mVGA_V_SYNC	<=	0;
			else
			mVGA_V_SYNC	<=	1;
		end
	end
end

endmodule